
use std::net::TcpListener;
use std::net::TcpStream;
use std::{
    io::{prelude::*, ErrorKind},
    thread,
};

fn main() {
    let listener = TcpListener::bind("127.0.0.1:23333").unwrap();

    // 有请求过来就新开一个线程来处理
    for client in listener.incoming() {
        let client = client.unwrap();
        thread::spawn(move || {
            handle_connection(client);
        });
    }
}

// 拷贝数据，用于转发浏览器和服务器之间的数据
fn copy(from: &mut TcpStream, to: &mut TcpStream) -> std::io::Result<u64> {

    // 以下代码是赋值  std::io::copy 函数的代码来修改的 
    let mut len = 0;
    loop {
        let mut buf = [0; 10240];

        match from.read(&mut buf) {
            Ok(0) => {
                return Ok(len);
            }
            Ok(bytes_read) => {
                len += bytes_read as u64;
                to.write(&buf[..bytes_read])?;
                println!("read:{}", bytes_read);
                continue;
            }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => {
                return Err(e);
            }
        }
    }
}

fn handle_connection(mut client: TcpStream) {
    let mut buf = [0; 4096];
    client.read(&mut buf).unwrap();

    let req = String::from_utf8_lossy(&buf).to_string();
    // println!("str:{}", req);

    // 空格分隔获取请求方式，用于后面区分 CONNECT 和其他类型
    let data: Vec<&str> = req.split(" ").collect();
    let mut server;

    // https隧道代理
    if data[0] == "CONNECT" {
        // 连接目标服务器
        server = TcpStream::connect(data[1]).unwrap();
        println!("链接服务器{}, {}", data[0], data[1]);

        // 连接目标成功之后，返回下面内容，表示 通知浏览器连接成功
        client
            .try_clone()
            .unwrap()
            .write_all(b"HTTP/1.0 200 Connection Established\r\n\r\n")
            .unwrap();
    } else {
        // http代理

        // 解析 http 协议，获取 目标主机
        let data: Vec<&str> = req.split("\r\n").collect();
        let mut host = String::new();
        for line in data {
            let t: Vec<&str> = line.split(": ").collect();
            if t[0].eq_ignore_ascii_case("host") {
                host = t[1].to_string();
                if !t[1].contains(":") {
                    host += ":80";
                }
                println!("链接服务器:{}", t[1]);
            }
        }

        // 如果目标主机为空，表示数据格式不对，直接返回
        if host.is_empty() {
            return;
        }

        // 连接目标服务器，将受到的数据直接转发到目标服务器
        server = TcpStream::connect(host).unwrap();
        server.write(&buf).unwrap();
    }

    // 下面两个线程(主线程和子线程)分别转发 服务端=>浏览器 和  浏览器=>客户端 的数据
    let mut client1 = client.try_clone().unwrap();
    let mut server1 = server.try_clone().unwrap();
    let t1 = thread::spawn(move || {
        copy(&mut server1, &mut client1).expect("服务端传输到客户端出错");
    });

    copy(&mut client, &mut server).expect("客户端传输到服务端出错");

    t1.join().unwrap();
}
